
package com.hlkj.pay.app.merchant.impl;

import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.merchant.IMerchantConfigAppService;
import com.hlkj.pay.common.constants.MqConstant;
import com.hlkj.pay.config.ExtRocketMQTemplate;
import com.hlkj.pay.dto.merchant.config.MerchantReportConfigDto;
import com.hlkj.pay.dto.merchant.report.MerchantReportConsumerDto;
import com.hlkj.pay.dto.merchant.report.MerchantReportDto;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.infrastructure.model.merchant.MerchantReportInfoDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.service.merchant.IMerchantReportService;
import com.hlkj.pay.service.pay.IProviderService;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author HlpayTeam
 * @date 2024/09/25 13:09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MerchantReportStatusProcessHandler {

    private final IMerchantReportService merchantReportService;

    private final IMerchantConfigAppService merchantConfigAppService;

    private final IProviderService providerService;

    private final ExtRocketMQTemplate extRocketMQTemplate;

    private final MerchantReportChannelService merchantReportChannelService;

    public void processReportMessage(MerchantReportConsumerDto merchantReportConsumerDto) {
        processReportMessage(merchantReportConsumerDto, null);
    }

    public void processReportMessage(Long id) {
        MerchantReportConsumerDto merchantReportConsumerDto = new MerchantReportConsumerDto();
        merchantReportConsumerDto.setReportId(id);
        processReportMessage(merchantReportConsumerDto, null);
    }

    public void processReportMessage(MerchantReportConsumerDto merchantReportConsumerDto, Integer merchantAccessQuestType) {
        log.info("processReportMessage data:{}", JsonUtils.toJsonStringNotNull(merchantReportConsumerDto));
        Long id = merchantReportConsumerDto.getReportId();
        MerchantReportDto merchantAccessDto = merchantReportService.domainDetail(id);
        if (merchantAccessDto == null) {
            log.warn("processReportMessage 数据不存在 id:{}", id);
            return;
        }
        MerchantReportInfoDO merchantReportInfo = merchantAccessDto.getMerchantReportInfo();
        MerchantEnum.REPORT_STATUS reportStatus = MerchantEnum.REPORT_STATUS.from(merchantReportInfo.getStatus());
        MerchantEnum.REPORT_BANK_STATUS reportBankStatus = MerchantEnum.REPORT_BANK_STATUS.from(merchantReportInfo.getBankStatus());
        MerchantEnum.MERCHANT_REPORT_QUEST_TYPE reportQuestType;
        if (merchantAccessQuestType != null) {
            reportQuestType = MerchantEnum.MERCHANT_REPORT_QUEST_TYPE.from(merchantAccessQuestType);
        }
        else {
            reportQuestType = MerchantEnum.MERCHANT_REPORT_QUEST_TYPE.from(reportStatus, reportBankStatus);
        }
        if (reportQuestType == null) {
            if (reportBankStatus == null) {
                log.info("当前无需进行状态处理,当前报备状态为 id:{},accessStatus:{}", id, reportStatus.getDesc());
            }
            else {
                log.info("当前无需进行状态处理,当前报备状态为 id:{},accessStatus:{},reportBankStatus:{}", id, reportStatus.getDesc(), reportBankStatus.getDesc());
            }
            return;
        }
        else {
            log.info("当前需要进行状态处理,当前报备状态为 id:{},reportQuestType:{}", id, reportQuestType.getDesc());
        }
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantReportInfo.getProviderCode(), merchantReportInfo.getChannelCode());
        MerchantReportConfigDto merchantReportConfigDto = merchantConfigAppService.queryReportConfig(merchantReportInfo.getSn());

        MerchantReportInfoDO updateMerchantReportInfoDO = new MerchantReportInfoDO();
        updateMerchantReportInfoDO.setId(id);
        if (merchantReportConfigDto == null) {
            updateMerchantReportInfoDO.setStatus(MerchantEnum.REPORT_STATUS.APPROVE_REFUSE.getCode());
            updateMerchantReportInfoDO.setMessage("商户汇电通配置为空");
            merchantReportService.updateReportInfo(updateMerchantReportInfoDO);
            log.error("当前需要进行状态处理,商户报备配置为空 id:{},sn:{}", id, merchantReportInfo.getSn());
            return;
        }
        if (providerChannelConfigDO == null || !StringUtils.hasText(providerChannelConfigDO.getParamsConfig())) {
            updateMerchantReportInfoDO.setStatus(MerchantEnum.REPORT_STATUS.APPROVE_REFUSE.getCode());
            updateMerchantReportInfoDO.setMessage("通道参数配置为空");
            merchantReportService.updateReportInfo(updateMerchantReportInfoDO);
            log.error("当前需要进行状态处理,通道参数配置为空 id:{},sn:{}", id, merchantReportInfo.getSn());
            return;
        }
        boolean extensionExist = merchantReportChannelService.extensionExist(merchantReportInfo.getChannelCode());
        if (!extensionExist) {
            updateMerchantReportInfoDO.setStatus(MerchantEnum.REPORT_STATUS.APPROVE_REFUSE.getCode());
            updateMerchantReportInfoDO.setMessage("当前通道报备未实现,请切换其他通道");
            merchantReportService.updateReportInfo(updateMerchantReportInfoDO);
            return;
        }
        boolean process = true;
        switch (reportQuestType) {
            case APPLY:
                merchantReportChannelService.processReportApply(merchantAccessDto);
                break;
            case SIGN:
                merchantReportChannelService.processSign(merchantAccessDto);
                break;
            case SIGN_QUERY:
                merchantReportChannelService.processSignQuery(merchantAccessDto);
                break;
            case APPLY_QUERY:
                merchantReportChannelService.applyQuery(merchantAccessDto);
                break;
            case ALLOT:
                merchantReportChannelService.allot(merchantAccessDto);
                break;
            case ALLOT_QUERY:
                merchantReportChannelService.allotQuery(merchantAccessDto);
                break;
            case PAYMENT:
                merchantReportChannelService.payment(merchantAccessDto);
                break;
            case SYNC_CHANNEL:
                merchantReportChannelService.syncChannel(merchantAccessDto);
                process = false;
                break;
            default:
                log.info("报备流程处理器 当前状态无需处理 id:{},status:{}", id, reportStatus.getDesc());

        }
        if (process) {
            nextProcessReportMessage(merchantReportConsumerDto, merchantAccessQuestType);
        }
    }

    public void nextProcessReportMessage(MerchantReportConsumerDto merchantReportConsumerDto, Integer merchantAccessQuestType) {
        Long id = merchantReportConsumerDto.getReportId();
        log.info("nextProcessReportMessage id:{}", id);
        MerchantReportInfoDO merchantReportInfo = merchantReportService.detail(id);
        MerchantEnum.REPORT_STATUS reportStatus = MerchantEnum.REPORT_STATUS.from(merchantReportInfo.getStatus());
        MerchantEnum.REPORT_BANK_STATUS reportBankStatus = MerchantEnum.REPORT_BANK_STATUS.from(merchantReportInfo.getBankStatus());
        MerchantEnum.MERCHANT_REPORT_QUEST_TYPE reportQuestType;
        if (merchantAccessQuestType != null) {
            reportQuestType = MerchantEnum.MERCHANT_REPORT_QUEST_TYPE.from(merchantAccessQuestType);
        }
        else {
            reportQuestType = MerchantEnum.MERCHANT_REPORT_QUEST_TYPE.from(reportStatus, reportBankStatus);
        }
        if (reportQuestType == null) {
            if (reportBankStatus == null) {
                log.info("当前无需进行状态处理,当前报备状态为 id:{},accessStatus:{}", id, reportStatus.getDesc());
            }
            else {
                log.info("当前无需进行状态处理,当前报备状态为 id:{},accessStatus:{},reportBankStatus:{}", id, reportStatus.getDesc(), reportBankStatus.getDesc());
            }
            return;
        }
        else {
            log.info("当前需要进行状态处理,当前报备状态为 id:{},reportQuestType:{}", id, reportQuestType.getDesc());
        }
        boolean queryProcess = false;
        switch (reportQuestType) {
            case APPLY_QUERY:
            case SIGN_QUERY:
            case ALLOT_QUERY:
                queryProcess = true;
                break;

        }
        if (queryProcess) {
            sendMerchantQuestReportMessage(merchantReportConsumerDto);
        }
        else {
            sendMerchantReportMessage(merchantReportConsumerDto);
        }
    }

    public void sendMerchantReportMessage(MerchantReportConsumerDto merchantAccessConsumerDto) {
        String jsonString = JsonUtils.toJsonString(merchantAccessConsumerDto);
        log.info("sendMerchantReportMessage:{}", jsonString);
        extRocketMQTemplate.send(MqConstant.MERCHANT_REPORT_STATUS_TOPIC, jsonString);
    }

    public void sendMerchantQuestReportMessage(MerchantReportConsumerDto merchantReportConsumerDto) {
        if (merchantReportConsumerDto.getDelayLevel() == null) {
            merchantReportConsumerDto.setDelayLevel(4);
        }
        else {
            // 延迟消息支持的时间 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
            if (merchantReportConsumerDto.getDelayLevel() < 15) {
                merchantReportConsumerDto.setDelayLevel(merchantReportConsumerDto.getDelayLevel() + 1);
            }
        }
        merchantReportConsumerDto.setDelaySendTime(System.currentTimeMillis());
        String jsonString = JsonUtils.toJsonString(merchantReportConsumerDto);
        log.info("sendMerchantQuestReportMessage:{}", jsonString);
        extRocketMQTemplate.sendDelay(merchantReportConsumerDto.getDelayLevel(), MqConstant.MERCHANT_REPORT_STATUS_TOPIC, jsonString);
    }
}
